package com.ncmmall.api.apis.mall;

import com.ncmmall.api.apis.service.Result;
import com.ncmmall.api.params.ShoppingCardDTO;
import com.ncmmall.api.params.ShoppingCardRecordDTO;
import com.ncmmall.api.security.Securitys;
import com.ncmmall.application.business.marketing.ShoppingCardOrderApplication;
import com.ncmmall.application.business.marketing.ShoppingCardRecordApplication;
import com.feijin.commons.lang.Requires;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCard;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardChannel;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardGoods;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardMerchant;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardOrder;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardRecord;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCard;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardChannel;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardGoods;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardMerchant;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardOrder;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardRecord;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardRecordConsume;
import com.ncmmall.domain.business.order.Order;
import com.ncmmall.domain.business.order.OrderDetail;
import com.ncmmall.domain.business.order.aftersale.OrderAfterSale;
import com.ncmmall.domain.business.order.aftersale.QOrderAfterSale;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.collect.ImmutableMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 购物卡
 *
 * @author likaikai
 * @date 2020-01-17 16:11:36
 */
@RestController
@RequestMapping("/shoppingCard")
@Slf4j
public class ShoppingCardApi {

    @Autowired
    private QueryChannelService queryChannelService;

    @Autowired
    private ShoppingCardRecordApplication shoppingCardRecordApplication;

    @Autowired
    private ShoppingCardOrderApplication shoppingCardOrderApplication;

    @Value("${store.domain}")
    private String storeDomain;

    /**
     * 购物卡中心列表
     */
    @GetMapping("/center")
    public Result center(@RequestParam(defaultValue = "1") int pageNo, @RequestParam(defaultValue = "10") int pageSize) {
        Result result = new Result();
        try {
            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize);
            QueryPage<ShoppingCard> page = queryChannelService.findPage("select s from ShoppingCard s where s.status = 2 and s.number > s.saleNumberCount order by s.enableTime desc", pageRequest, ShoppingCard.class);


            for (ShoppingCard card : page.getResult()) {
                if (card.getValidType() == 1) {
                    card.setStartTime(DateFormatUtils.format(card.getValidStartTime(), "yyyy-MM-dd"));
                    card.setEndTime(DateFormatUtils.format(card.getValidEndTime(), "yyyy-MM-dd"));
                }
            }
            return result.ok().inject(ImmutableMap.of("page", page));

        } catch (Exception e) {
            log.error("[获取购物卡中心数据异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }


    /**
     * 购物卡可用商品
     */
    @GetMapping("/{id}/goods")
    public Result goods(@RequestParam(defaultValue = "1") int pageNo, @RequestParam(defaultValue = "10") int pageSize, @PathVariable long id) {
        Result result = new Result();
        try {
            ShoppingCard card = queryChannelService.findOne(QShoppingCard.shoppingCard.id.eq(id), ShoppingCard.class);
            Requires.notNull(card, "购物卡不存在");
            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize);

            //品类，商家，商品
            List<ShoppingCardGoods> cardGoodses = queryChannelService.findAll(QShoppingCardGoods.shoppingCardGoods.shoppingCard.id.eq(card.getId()), ShoppingCardGoods.class);
            List<ShoppingCardChannel> cardChannels = queryChannelService.findAll(QShoppingCardChannel.shoppingCardChannel.shoppingCard.id.eq(card.getId()), ShoppingCardChannel.class);
            List<ShoppingCardMerchant> cardMerchants = queryChannelService.findAll(QShoppingCardMerchant.shoppingCardMerchant.shoppingCard.id.eq(card.getId()), ShoppingCardMerchant.class);

            String hql = "select g from Goods g where g.status = 3 and g.isSupplier = 0";
            Map<String, Object> map = new HashMap<>();

            if (CollectionUtils.isNotEmpty(cardChannels)) {
                List<Long> channelids = cardChannels.stream().map(item -> item.getGoodsChannel().getId()).collect(Collectors.toList());
                hql += " and g.goodsChannel.parent.parent.id in (:channelids)";
                map.put("channelids", channelids);
            }

            if (CollectionUtils.isNotEmpty(cardGoodses)) {
                List<Long> goodsIds = cardGoodses.stream().map(item -> item.getGoods().getId()).collect(Collectors.toList());
                hql += " and g.id in (:goodsIds)";
                map.put("goodsIds", goodsIds);
            }

            if (CollectionUtils.isNotEmpty(cardMerchants)) {
                List<Long> merchantIds = cardMerchants.stream().map(item -> item.getMerchant().getId()).collect(Collectors.toList());
                hql += " and g.merchant.id in (:merchantIds)";
                map.put("merchantIds", merchantIds);
            }

            hql += "order by g.createTime desc";


            QueryPage<Goods> page = queryChannelService.findPage(hql, pageRequest.setParams(map), Goods.class);

            for (Goods goods : page.getResult()) {
                goods.setSkus(null);
                goods.setContent(null);
                goods.setGoodsChannel(null);
                goods.setSaleAttributes(null);
                goods.setParamses(null);
                goods.setImages(null);
                if (StringUtils.isNotBlank(goods.getDefaultImage())) {
                    goods.setDefaultImage(storeDomain + "/uploads/" + goods.getDefaultImage());
                }
            }
            return result.ok().inject(ImmutableMap.of("page", page));

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取购物卡可用商品数据异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }


    /**
     * 用户购物卡列表
     *
     * @param status 购物卡状态
     *               1、可使用
     *               2、已用完
     *               3、已转增
     *               4、已过期
     */
    @GetMapping("/list")
    public Result list(HttpServletRequest request, @RequestParam(defaultValue = "0") int status,
                       @RequestParam(defaultValue = "1") int pageNo,
                       @RequestParam(defaultValue = "10") int pageSize) {
        Result result = new Result();
        try {
            WebUser user = Securitys.user(request);

            Map<String, Object> map = new HashMap<>();
            String sql = buildListHql(status, user, map);

            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize).setParams(map);
            QueryPage<ShoppingCardRecord> page = queryChannelService.findPage(sql, pageRequest, ShoppingCardRecord.class);

            int c1 = queryChannelService.selectCount("select count(*) from mall_shopping_card_record where user_id = :uid and status = 1", ImmutableMap.of("uid", user.getId()));
            int c2 = queryChannelService.selectCount("select count(*) from mall_shopping_card_record where user_id = :uid and status = 2", ImmutableMap.of("uid", user.getId()));
            int c3 = queryChannelService.selectCount("select count(*) from mall_shopping_card_record where user_id = :uid and status = 3", ImmutableMap.of("uid", user.getId()));
            int c4 = queryChannelService.selectCount("select count(*) from mall_shopping_card_record where user_id = :uid and status = 4", ImmutableMap.of("uid", user.getId()));

            return result.ok().inject(ImmutableMap.of("page", page, "c1", c1, "c2", c2, "c3", c3, "c4", c4));

        } catch (IllegalArgumentException e) {

            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取用户购物卡列表异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }

    private String buildListHql(int status, WebUser user, Map<String, Object> map) {

        String sql = "select r from ShoppingCardRecord r where r.user.id = :uid";
        map.put("uid", user.getId());

        if (status > 0) {
            sql += " and r.status = :status";
            map.put("status", status);
        }

        if (status == 1) {
            sql += " and r.balance > 0";
        }

        sql += " order by r.createTime desc";
        return sql;
    }


    /**
     * 购物卡赠送好友
     */
    @PostMapping("/givenFriend")
    public Result givenFriend(HttpServletRequest request, @RequestBody ShoppingCardRecordDTO params) {
        Result result = new Result();
        try {
            WebUser user = Securitys.user(request);

            ShoppingCardRecord record = queryChannelService.findOne(QShoppingCardRecord.shoppingCardRecord.id.eq(params.getId()).and(QShoppingCardRecord.shoppingCardRecord.user.id.eq(user.getId())), ShoppingCardRecord.class);
            Requires.notNull(record, "购物卡不存在");
            Requires.isTrue(record.getStatus() != 2, "该购物卡已用完");
            Requires.isTrue(record.getStatus() != 3, "该购物卡已被赠送");
            Requires.isTrue(record.getShoppingCard().getStatus() == 2, "该购物卡已过期");
            Requires.isTrue(!user.getMobile().equals(params.getMobile()), "不能赠送给自己");

            WebUser friend = queryChannelService.findOne(QWebUser.webUser.mobile.eq(params.getMobile()).and(QWebUser.webUser.role.name.eq("MEMBER")), WebUser.class);
            Requires.notNull(friend, "用户不存在");

            shoppingCardRecordApplication.givenFriend(record, friend);
            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[购物卡赠送好友异常]", e);
            return result.fail().setMsg("赠送异常");
        }
    }

    /**
     * 购物卡取消支付
     */
    @PutMapping("/cancelPay")
    public Result cancelPay(HttpServletRequest request, long orderId) {
        Result result = new Result();
        try {
            WebUser user = Securitys.user(request);
            ShoppingCardOrder order = queryChannelService.findOne(QShoppingCardOrder.shoppingCardOrder.id.eq(orderId).and(QShoppingCardOrder.shoppingCardOrder.user.id.eq(user.getId())), ShoppingCardOrder.class);
            Requires.notNull(order, "购物卡订单不存在");

            shoppingCardOrderApplication.cancel(order);
            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[取消购物卡订单异常]", e);
            return result.fail().setMsg("取消购物卡订单异常");
        }
    }


    /**
     * 购物卡消费记录
     *
     * @param id 购物卡id
     */
    @GetMapping("/consume")
    public Result comsume(long id, @RequestParam(defaultValue = "1") int pageNo,
                          @RequestParam(defaultValue = "10") int pageSize, HttpServletRequest request) {
        Result result = new Result();
        try {
            WebUser user = Securitys.user(request);
            ShoppingCardRecord record = queryChannelService.findOne(QShoppingCardRecord.shoppingCardRecord.id.eq(id).and(QShoppingCardRecord.shoppingCardRecord.user.id.eq(user.getId())), ShoppingCardRecord.class);
            Requires.notNull(record, "购物卡不存在");

            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize).setParams(ImmutableMap.of("rid", record.getId()));
            QueryPage<ShoppingCardRecordConsume> page = queryChannelService.findPage("select c from ShoppingCardRecordConsume c where c.shoppingCardRecord.id = :rid order by c.createTime desc", pageRequest, ShoppingCardRecordConsume.class);

            for (ShoppingCardRecordConsume consume : page.getResult()) {
                Order order = consume.getOrder();
                if (order.getIsAfterSale() == 1) {
                    order.setOrderAfterSaleId(queryChannelService.findOne(QOrderAfterSale.orderAfterSale.order.id.eq(order.getId()), OrderAfterSale.class).getId());
                }
                if (null != order.getCoupon() && null != order.getCoupon().getComplimentaryGoods()) {
                    order.getCoupon().getComplimentaryGoods().setDefaultImage(storeDomain + "/uploads/" + order.getCoupon().getComplimentaryGoods().getDefaultImage());
                }
                for (OrderDetail detail : order.getDetails()) {
                    detail.setDefaultImage(storeDomain + "/uploads/" + detail.getDefaultImage());
                    detail.setGoodsId(detail.getSku().getGoods().getId());
                }
            }

            return result.ok().inject(page);

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[获取购物卡消费记录异常]", e);
            return result.fail().setMsg("获取数据异常");
        }
    }


    /**
     * 购物卡过期申请激活
     */
    @PostMapping("/{id}/activateApply")
    public Result activateApply(@PathVariable long id, @RequestBody ShoppingCardDTO r, HttpServletRequest request) {
        Result result = new Result();
        try {
            ShoppingCardRecord record = queryChannelService.findOne(QShoppingCardRecord.shoppingCardRecord.id.eq(id), ShoppingCardRecord.class);

            Requires.notNull(record, "购物卡不存在");
            Requires.isTrue(record.getUser().getId() == Securitys.user(request).getId(), "购物卡不存在");
            Requires.isTrue(record.getStatus() == 4 && record.getBalance() > 0, "当前购物卡无需激活");

            Requires.hasLength(r.getActivateApplyNote(), "请输入申请原因");
            shoppingCardRecordApplication.activateApply(record, r.getActivateApplyNote());

            return result.ok();

        } catch (IllegalArgumentException e) {
            return result.fail().setMsg(e.getMessage());
        } catch (Exception e) {
            log.error("[购物卡申请激活异常]", e);
            return result.fail().setMsg("申请失败");
        }
    }

}
